﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
enum DrawNavMeshFlags
{
    DU_DRAWNAVMESH_OFFMESHCONS = 0x01,
    DU_DRAWNAVMESH_CLOSEDLIST = 0x02,
    DU_DRAWNAVMESH_COLOR_TILES = 0x04,
};

[RequireComponent(typeof(RaceLogic))]
public class MapRenderForMesh : MonoBehaviour
{
    [DllImport("recast")]
    static extern void get_mesh_info(IntPtr ptr, ref int vcnt,ref int tcnt);
    [DllImport("recast")]
    static extern void get_mesh_vertexs(IntPtr ptr, long[] data, int length);
    [DllImport("recast")]
    static extern void get_mesh_triangles(IntPtr ptr, int[] data, int length);
    [DllImport("recast")]
    static extern void get_nav_mesh_graphics(IntPtr ptr,byte flags,long[] data, ref int dlen, uint[] colors,ref int clen);

    /// <summary>
    /// 渲染控制数据
    /// </summary>
    [SerializeField]
    protected Material LineMat;
    [SerializeField]
    protected Color LineColor = new Color(1, 1, 1, 1);

    RaceLogic raceLogic;

    /// <summary>
    /// 原始几何绘制数据
    /// </summary>
    [SerializeField]
    [Tooltip("原始几何Y轴偏移")]
    protected float meshOffsetY = 0.0f;
    long[] verts;
    int[] tris;
    int vcnt;
    int tcnt;
    double l2d = 1.0 / 65536;

    /// <summary>
    /// 导航网格数据
    /// </summary>
    [SerializeField]
    [Tooltip("导航网格Y轴偏移")]
    protected float navMeshOffsetY = 0.0f;
    long[] nav_mesh_verts = new long[4096];
    int nav_mesh_length = 4096;
    uint[] colors = new uint[4096];
    int clen = 4096;
    byte flags = 0;
    [SerializeField]
    bool drawNavMeshClosedList = true;
    [SerializeField]
    bool drawNavMeshOffMeshCons = true;
    [SerializeField]
    bool drawNavMeshColorTiles = false;

    static float cradio = 1.0f / 255.0f;
    static Color fourcc(uint c)
    {
        Color rc;
        rc.r = (c & 0xFF)* cradio;
        rc.g = ((c >> 8) & 0xFF) * cradio;
        rc.b = ((c >> 16) & 0xFF)* cradio;
        rc.a = ((c >> 24) & 0xFF)*cradio;
        return rc;
    }

    private void Awake()
    {
        raceLogic = GetComponent<RaceLogic>();
    }

    private void Update()
    {
        int targetFlags = 0;
        if (drawNavMeshOffMeshCons) targetFlags |= (int)DrawNavMeshFlags.DU_DRAWNAVMESH_OFFMESHCONS;
        if (drawNavMeshClosedList) targetFlags |= (int)DrawNavMeshFlags.DU_DRAWNAVMESH_CLOSEDLIST;
        if (drawNavMeshColorTiles) targetFlags |= (int)DrawNavMeshFlags.DU_DRAWNAVMESH_COLOR_TILES;
        if (((byte)targetFlags) != this.flags)
        {
            this.flags = ((byte)targetFlags);
            if(null != raceLogic)
                get_nav_mesh_graphics(raceLogic.Handle(), flags, nav_mesh_verts, ref nav_mesh_length, colors, ref clen);
        }
    }

    private void Start()
    {
        if(null != raceLogic && IntPtr.Zero != raceLogic.Handle())
        {
            get_mesh_info(raceLogic.Handle(), ref vcnt, ref tcnt);
            verts = new long[vcnt];
            tris = new int[tcnt];
            get_mesh_vertexs(raceLogic.Handle(), verts,vcnt);
            get_mesh_triangles(raceLogic.Handle(), tris,tcnt);
        }
    }

    void drawV(long[] p,int idx,Color color,float yoffset = 0.0f)
    {
        GL.Color(color);
        float x = (float)(-p[idx] * l2d);
        float y = (float)(p[idx + 1] * l2d) + yoffset;
        float z = (float)(p[idx + 2] * l2d);
        GL.Vertex3(x,y,z);
    }

    private void OnRenderObject()
    {
        if (null != LineMat)
        {
            LineMat.SetColor("_Color", LineColor);
            LineMat.SetPass(0);
            GL.PushMatrix();
            GL.wireframe = true;
            GL.Begin(GL.TRIANGLES);
            for (int i = 0; i < tcnt; i += 3)
            {
                
                drawV(verts, tris[i] * 3, Color.blue, meshOffsetY);
                drawV(verts, tris[i + 2] * 3, Color.blue, meshOffsetY);
                drawV(verts, tris[i + 1] * 3, Color.blue, meshOffsetY);
            }
            GL.End();
            GL.wireframe = false;
            GL.Begin(GL.TRIANGLES);
            for(int i = 0,j=0; i < nav_mesh_length;i+=9,++j)
            {
                var c = fourcc(colors[j]);
                drawV(nav_mesh_verts,i, c, navMeshOffsetY);
                drawV(nav_mesh_verts, i+6, c, navMeshOffsetY);
                drawV(nav_mesh_verts, i + 3,c, navMeshOffsetY);
            }
            GL.End();
            GL.wireframe = false;
            GL.PopMatrix();
        }
    }
}